package sanshui.system.trade.factory.trade.strategy.impl;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import sanshui.system.trade.factory.data.Bar;
import sanshui.system.trade.factory.trade.TradeSystemContext;
import sanshui.system.trade.factory.trade.indicator.IndicatorResult;
import sanshui.system.trade.factory.trade.strategy.AbstractStrategy;
import sanshui.system.trade.factory.trade.strategy.StrategyCallType;
import sanshui.system.trade.factory.trade.strategy.StrategyCode;
import sanshui.system.trade.factory.trade.strategy.StrategyResult;
import sanshui.system.trade.util.DataParseUtil;
import sanshui.system.trade.util.IndicatorUtil;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 经典海龟策略
 * */
@Slf4j
@Component
public class TurtleTradingStrategy  extends AbstractStrategy {

    private final int entryWindow = 20; // 入场窗口
    private final int exitWindow = 10;  // 出场窗口
    private final List<Long> hisATR = new ArrayList<>(); // 平均波动
    private final int ATR_N_14 = 14;
    private final List<Long> hisTR = new ArrayList<>(); // 真实波动

    @Override
    public StrategyCode getStrategyCode() {
        return StrategyCode.TURTLE;
    }

    @Override
    public IndicatorResult execCustom(Bar currentData, TradeSystemContext tradeSystemContext) {
        IndicatorResult indicatorResult = IndicatorResult.buildNothing(currentData.symbol, currentData);
        List<Bar> data = tradeSystemContext.getDataCache().getHisPriceDataMap().get(currentData.getSymbol());

        Map<String, List<String>> paramMap = new HashMap<>();

        if (data.size() <= Math.max(entryWindow, exitWindow)){
            paramMap.put("ATR14", new ArrayList<>());
            paramMap.put("TR", new ArrayList<>());
            indicatorResult.setParamMap(paramMap);
            return indicatorResult;
        }

        Long tr = IndicatorUtil.calculateTR(data.get(data.size()-2), data.get(data.size()-1));
        this.addHisValue(tr, hisTR);

        Long atr14 = IndicatorUtil.calculateATR(ATR_N_14, hisTR);
        this.addHisValue(atr14, hisATR);
        paramMap.put("ATR14", DataParseUtil.parseToStringList(hisATR));

        indicatorResult.setParamMap(paramMap);
        return indicatorResult;
    }

    /**
     * SELL : TR > 2ATR
     * BUY : EMA5 > MA5
     * */
    @Override
    public StrategyResult exec(String code, IndicatorResult indicatorResult, TradeSystemContext tradeSystemContext) {
        StrategyResult strategyResult = StrategyResult.buildNothing(code);

        List<Bar> hisDataBar = tradeSystemContext.getDataCache().getHisPriceDataMap().get(code);
        List<String> atr14 = indicatorResult.getParamMap().get("ATR14");
        if (atr14.size() == 0){
            return strategyResult;
        }
        Long currenAtr = Long.valueOf(atr14.get(atr14.size() - 1));

        Bar currentData = indicatorResult.getCurrentBar();
        double entryHigh = IndicatorUtil.calculateMaxHigh(entryWindow, hisDataBar);

        if (currentData.close > entryHigh) {
            // 开多仓
            strategyResult.setStrategyCallType(StrategyCallType.BUY);
            Long entryPrice = currentData.close;
            strategyResult.setPrice(entryPrice);
        }
        // 寻找出场信号
        double exitLow = IndicatorUtil.calculateMinLow(exitWindow, hisDataBar);
        if (currentData.close < exitLow) {
            // 平多仓
            strategyResult.setStrategyCallType(StrategyCallType.SELL);
            Long exitPrice = currentData.close;
            strategyResult.setPrice(exitPrice);
        }
        return strategyResult;
    }


}
